package com.projectsquirrel;

import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

public class LocListener implements LocationListener{
	private LocationManager myManager;
	private Context appContext;
	private double latitude;
	private double longitude;
	private String ZipCode;
	private Geocoder geocoder;
	private static LocListener instance = null;
	private boolean isNewLocation = true;
	public LocListener(LocationManager m, Context c){
		myManager = m;
		appContext = c;
		geocoder = new Geocoder(c, Locale.getDefault() );
	}
	
	public static LocListener getInstance(LocationManager m,Context c){
		if(instance==null){
			instance= new LocListener(m,c);
		}
		return instance;
	}
	public double getLatitude(){
		return latitude;
	}
	public double getLongitude(){
		return longitude;
	}
	public String getZipCode(){
		return ZipCode;
	}
	//GPS required methods---
	public void startListeningNetwork() {
		if(!isAirplaneModeOn(appContext)){
			if(myManager.getBestProvider(createCoarseCriteria(), true) != null)
			{
				LocationProvider low= myManager.getProvider(myManager.getBestProvider(createCoarseCriteria(), true));
				myManager.requestLocationUpdates(low.getName(), 0, 0F, this);
			}
		}
	}
	public void startListeningGPS() {
		if(!isAirplaneModeOn(appContext)){
			LocationProvider high= myManager.getProvider(myManager.getBestProvider(createFineCriteria(), true));
			myManager.requestLocationUpdates(high.getName(), 0, 0F, this);
		}
	}
	public void startGPS() {
		if(!isAirplaneModeOn(appContext)){
			myManager.requestLocationUpdates(myManager.GPS_PROVIDER, 0, 0F, this);
		}
	}
	public void stopListening() {
		if (myManager != null)
			myManager.removeUpdates(this);
	}
	
	public void onLocationChanged(Location location) {
		if(isNewLocation){
			Toast.makeText(appContext, "Acquired location.", 5000).show();
			isNewLocation=false;
		}
		else{
			stopListening();
		}
		latitude = location.getLatitude();
		longitude = location.getLongitude();
		
		try{
	        List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
	        ZipCode = addresses.get(0).getPostalCode();
	        }
	        catch(Exception e){
	        	Log.e("Geocoder Error:", e.toString());
	        }
		
	}

	public void onProviderDisabled(String provider) {
			
		if(provider.equalsIgnoreCase(myManager.NETWORK_PROVIDER)){
			startListeningGPS();
		}
		else if (provider.equalsIgnoreCase(myManager.GPS_PROVIDER)){
			//Toast.makeText(this, "GPS Disabled", 1000).show();
		}
		else{
			//Toast.makeText(this, "OTHER Disabled", 1000).show();
		};
	}

	public void onProviderEnabled(String provider) {
		
		if(provider.equalsIgnoreCase(myManager.NETWORK_PROVIDER)){
			//Toast.makeText(this, "Network Location Enabled Trying For Location...", 7000).show();
			startListeningNetwork();
			if(!isAirplaneModeOn(appContext)){
			}
			
		}
		if(provider.equalsIgnoreCase(myManager.GPS_PROVIDER)){
			//Toast.makeText(this, "GPS Location Service Enabled Trying GPS...", 7000).show();
			startListeningGPS();
		}
		
		
	}
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
		
	}

	public static Criteria createCoarseCriteria() {

		  Criteria c = new Criteria();
		  c.setAccuracy(Criteria.ACCURACY_COARSE);
		  c.setAltitudeRequired(false);
		  c.setBearingRequired(false);
		  c.setSpeedRequired(false);
		  c.setCostAllowed(true);
		  c.setPowerRequirement(Criteria.NO_REQUIREMENT);
		  return c;

		}

		/** this criteria needs high accuracy, high power, and cost */
	public static Criteria createFineCriteria() {

		  Criteria c = new Criteria();
		  c.setAccuracy(Criteria.ACCURACY_FINE);
		  c.setAltitudeRequired(false);
		  c.setBearingRequired(false);
		  c.setSpeedRequired(false);
		  c.setCostAllowed(true);
		  c.setPowerRequirement(Criteria.NO_REQUIREMENT);
		  return c;

	}
	
	
	 private static boolean isAirplaneModeOn(Context context) {
	        return Settings.System.getInt(context.getContentResolver(),
	                Settings.System.AIRPLANE_MODE_ON, 0) != 0;

	    }  
	 public boolean airplaneMode() {
	        return isAirplaneModeOn(appContext);

	    } 
}
